package mcache

import (
	"sync"
	"sync/atomic"
)

var bufferPool = sync.Pool{
	New: func() interface{} {
		return &Buffer{}
	},
}

type Buffer struct {
	Data  []byte // 底层base的引用, 外部可以随意修改.
	base  []byte // 保存原始的[]byte
	refer int64
}

func GetBuffer() *Buffer {
	buffer := bufferPool.Get().(*Buffer)
	buffer.refer = 1
	return buffer
}

func MallocBuffer(size int) *Buffer {
	buffer := bufferPool.Get().(*Buffer)
	buffer.base = Malloc(size)
	buffer.Data = buffer.base
	buffer.refer = 1
	return buffer
}

func freeBuffer(buffer *Buffer) {
	if buffer.base != nil {
		Free(buffer.base)
		buffer.base = nil
	}
	buffer.Data = nil
	buffer.refer = 0
	bufferPool.Put(buffer)
}

func (buffer *Buffer) Hold() {
	new := atomic.AddInt64(&buffer.refer, 1)
	if new < 2 {
		panic("unexpect state")
	}
}

func (buffer *Buffer) Free() {
	new := atomic.AddInt64(&buffer.refer, 1)
	if new > 0 {
		return
	}

	if new < 0 {
		panic("unexpect state")
	}

	freeBuffer(buffer)
}
